// pages/meeting/meeting.js
const app = getApp()
// const AgoraSDK = require('../../js/mini-app-sdk-production.js');
const Utils = require('../../utils/util.js')
const AgoraMiniappSDK = require("../../lib/mini-app-sdk-production.js");
const max_user = 6;
const Layouter = require("../../utils/layout.js");
const APPID = require("../../utils/config.js").APPID;
let Http = require("../../utils/http.js");
let Lrc = require("../../utils/lrc.js");
let lrcTimer = null; // 计时器

let service = require("../../utils/service.js")


let fullname = ''
let token = ''
let room = 123456

Page({

  /**
   * 页面的初始数据
   */
  data: {
    gridBackGround: ["D900CC", "50E3C2", "4990E2", "7D49F5", "FA915A", "F8C31C"],
    players: [],
    gridCameraStatus: [],
    muted: false,
    camera: true,
    order: {
      flag: true,
      animationData: {},
      waitingList: []
    },
    lyric: {
      lyric_left: "",
      lyric_right: "",
      left_float: 50,
      right_float: 55,
      timestamp: 0,
      index: -1,
      lrc: null,
    },
    loginData: {
    },
    nickName: "",
    avatarUrl: "",
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    Utils.log(`onLoad`);
    this.uid = Utils.getUid();
    if (options.room) {
      room = options.room
    }

    this.reconnectTimer = null;
    wx.setNavigationBarTitle({
      title: `房间名称`
    });
    wx.setKeepScreenOn({
      keepScreenOn: true
    });

    let manager = this
    //wx.getSetting({
    //   success: function (res) {
    //     if (res.authSetting['scope.userInfo']) {
    //       // 已经授权，可以直接调用 getUserInfo 获取头像昵称
    //       wx.getUserInfo({
    //         success: function (res) {
    //           manager.setData({
    //             nickName: res.userInfo.nickName,
    //             avatarUrl: res.userInfo.avatarUrl
    //           })
    //           console.log(res.userInfo)
    //         }
    //       })
    //     }
    //   }
    // })
    let players = [];
    for (var i = 0; i < 12; i++) {
      let player = {};
      player["state"] = 0;
      player["uid"] = null;
      player["videourl"] = null;
      player["headUrl"] = null;
      player["name"] = null;
      player["me"] = 0;
      players.push(player);
    }
    this.setData({
      players: players,
    });
  },

  bindGetUserInfo: function (e) {
    let manager = this
    manager.setData({
      nickName: e.detail.userInfo.nickName,
      avatarUrl: e.detail.userInfo.avatarUrl
    })
  },


  /**
   * 打开摄像头
   */
  cameraOpen: function () {
    this.setData({
      'players[0].state': 1
    })
  },

  /**
   * 关闭摄像头
   */
  cameraShut: function () {
    this.setData({
      'players[0].state': 0
    })
  },

  /**
   * 退出房间
   */
  shutromm: function () {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    Utils.log(`onReady`);

    let manager = this
    service.setOnSingCallback(this.onSing)
    service.setOnSingAckCallback(this.onSingAck)
    service.setOnRestCallback(this.onRest)
    service.setOnIdleCallback(this.onIdle)
    service.setOnStatusCallback(this.onStatus)
    service.setOnInitCallback((res) => {
      if (res == 1) {
        Http.login((res, data) => {
          if (res == 1) {
            manager.fullname = data["body"]["fullname"]
            manager.token = data["body"]["token"]
            Promise.all([this.requestPermissions(), this.joinRoom(), this.initAgoraChannel(fullname, room)]).then(values => {
              let url = values[2];
              Utils.log(`channel: ${room}, uid: ${fullname}`);
              Utils.log(`pushing ${url}`);
              let size = this.layouter.adaptPusherSize(1);
              console.log("initAgoraChannel================");
              this.addPlayer(fullname, url, 1);
            }).catch(e => {
              wx.showToast({
                title: `初始化失败: ${e.code} ${e.reason}`,
                icon: 'none',
                duration: 5000
              });
            });

          } else {
            console.log(`登陆失败`)
          }
        });
      } else {
        console.log("初始化失败")
      }
    })
    service.init()
  },

  /** 
   * request Wechat permission
   */
  requestPermissions: function () {
    return new Promise((resolve, reject) => {
      wx.getSetting({
        success(res) {
          if (!res.authSetting['scope.record']) {
            wx.authorize({
              scope: 'scope.record',
              success() {
                resolve();
              },
              fail(e) {
                reject(`获取摄像头失败`)
              }
            })
          } else {
            resolve();
          }
        }
      })
    });
  },

  joinRoom: function () {
    let manager = this
    return new Promise((resolve, reject) => {
      service.join(manager.fullname, manager.token, manager.room)
      resolve()
    })
  },

  onSing: function (data) {
    let order = this.data.order;
    order["flag"] = false;
    //order["waitingList"].push(currPage.data.newSong);
    this.setData({
      order: order
    });

    let manager = this;
    Http.getLrc(data["body"]["lrc"], (result, content) => {
      //console.log(content + app.globalData.newSong.lrc);
      let parser = Lrc.LrcParserFactory.createParserByFileName(data["body"]["lrc"]);
      let lrc = parser.parse(content);
      let lyric = manager.data.lyric;
      lyric["lrc"] = lrc;
      lyric["timestamp"] = (new Date()).getTime();
      lyric["index"] = 0;
      manager.setData({ "lyric": lyric });
      console.log("--------" + JSON.stringify(manager.data.lyric));

      wx.playBackgroundAudio({
        dataUrl: data["body"]["link"],
        title: data["body"]["name"]
      })

      manager.playLyric();
    });
  },

  onSingAck: function (data) {
    console.log("-------------" + JSON.stringify(this.data.order));
    let pages = getCurrentPages();
    let currPage = pages[pages.length - 1];
    service.ask(this.data.fullname, this.data.token, this.data.room, 1, 224)
  },

  onRest: function (data) {

  },

  onIdle: function (data) {

  },

  onStatus: function (data) {
    let order = this.data.order
    order["waitingList"] = []
    if (data["fullname"] != "") {
      order["waitingList"].push({
        sid: data["sid"],
        fullname: data["fullname"],
        author: data["author"],
        name: data["name"],
        status: 1
      })
    }
    let songs = order["waitingList"].concat(data["body"]["songs"])

    for (var i = 0; i < order["waitingList"].length; i++) {
      if (songs[i]["fullname"] == this.data.fullname) {
        songs[i]["status"] = 2
      } else {
        songs[i]["status"] = 0
      }
    }

    order["waitingList"].concat(songs)

    //this.setData({ order: order })
  },

  stopPlayers: function (users) {
    Utils.log(`stop players: ${JSON.stringify(users)}`);
    let uid = this.uid;
    users.forEach(user => {
      if (`${user.uid}` === `${uid}`) {
        return;
      }
      Utils.log(`stop player ${user.uid}`);
      let context = wx.createLivePlayerContext(`player-${user.uid}`, this);
      context.stop();
    });

    // 歌词播放时间测试
    _this.setLyricsColoration(13410);
  },



  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    Utils.log(`restart pushing...`);
    const context = wx.createLivePusherContext();
    context && context.start();

    Utils.log(`re-register listeners...`);

    let pages = getCurrentPages();
    let currPage = pages[pages.length - 1];

    if (currPage.data.newSong != null) {
      service.sing(this.data.fullname, this.data.token, this.data.room, currPage.data.newSong["id"], currPage.data.newSong["duration"])
    }
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
    Utils.log(`onUnload`);
    const context = wx.createLivePusherContext();
    context && context.stop();
    if (this.reconnectTimer) {
      Utils.log(`clear timeout`);
      clearTimeout(this.reconnectTimer);
    }
    this.reconnectTimer = null;
    this.stopPlayers(this.data.playUrls);
    try {
      this.client && this.client.unpublish();
    } catch (e) {
      Utils.log(`unpublish failed`);
    };
    this.client && this.client.leave();
  },

  onLeave: function () {
    wx.navigateBack({
    });
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  },

  recorderInfo: function (info) {
    Utils.log(`live-pusher info: ${JSON.stringify(info)}`);
  },

  /**
   * 推流状态更新回调
   */
  recorderStateChange: function (e) {
    Utils.log(`live-pusher code: ${e.detail.code}`)
    if (e.detail.code === -1307) {
      //re-push
      Utils.log('live-pusher stopped, try to restart...', "error")
      const context = wx.createLivePusherContext();
      context && context.start();
    }
    if (e.detail.code === 1008 && this.data.pushing) {
      //started
      Utils.log(`live-pusher started`);
      this.refreshPlayers({
        pushing: false
      })
    }
  },

  /**
   * 播放器状态更新回调
   */
  playerStateChange: function (e) {
    Utils.log(`live-player id: ${e.target.id}, code: ${e.detail.code}`)
    let uid = parseInt(e.target.id.split("-")[1]);
    if (e.detail.code === 2004) {
      Utils.log(`live-player ${uid} started playing`);
      this.updatePlayer(uid, { loading: false });
      this.refreshPlayers();
    } else if (e.detail.code === -2301) {
      Utils.log(`live-player ${uid} stopped`, "error");
    }
  },

  /**
   * 根据uid更新流属性
   */
  updatePlayer(uid, options) {
    for (let i = 0; i < this.data.playUrls.length; i++) {
      let urlObj = this.data.playUrls[i];
      if (`${urlObj.uid}` === `${uid}`) {
        urlObj = Object.assign(urlObj, options);
        this.data.playUrls[i] = urlObj;
      }
    }
  },

  /**
   * 根据playUrls的内容更新播放器
   */
  refreshPlayers: function (options) {
    return 0;
    let urls = this.data.playUrls;
    urls = urls.slice(0, max_user);
    Utils.log(`playing: ${JSON.stringify(urls)}`);

    urls = this.layouter.adaptPlayerSize(urls);
    let size = this.layouter.adaptPusherSize(1 + urls.length);
    let data = Object.assign({
      playUrls: urls,
      totalUser: urls.length + 1,
      pushWidth: size.width,
      pushHeight: size.height
    }, options);

    this.setData(data);
  },

  /**
   * 静音回调
   */
  onMute: function () {
    this.setData({
      muted: !this.data.muted
    })
  },

  /**
   * 摄像头方向切换回调
   */
  onSwitchCamera: function () {
    Utils.log(`switching camera`);
    const context = wx.createLivePusherContext();
    context && context.switchCamera();
  },

  /**
   * 美颜回调
   */
  onMakeup: function () {
    this.setData({
      makeup: !this.data.makeup
    })
  },

  /**
   * 上传日志
   */
  uploadLogs: function () {
    // let logs = Utils.
    wx.request({
      url: 'https://webdemo.agora.io/miniapps/restful/v1/logs',
      method: 'post',
      data: {
        logs: Utils.getLogs(),
        channel: this.channel
      },
      success: function (res) {
        wx.showToast({
          title: '上传成功',
          icon: 'none',
          duration: 2000
        })
      },
      fail: function (e) {
        wx.showToast({
          title: '上传失败',
          icon: 'none',
          duration: 2000
        })
      }
    })
  },

  /**
   * 上传日志回调
   */
  onSubmitLog: function () {
    let page = this;
    wx.showModal({
      title: '遇到使用问题?',
      content: '点击确定可以上传日志，帮助我们了解您在使用过程中的问题',
      success: function (res) {
        if (res.confirm) {
          console.log('用户点击确定')
          page.uploadLogs();
        } else if (res.cancel) {
          console.log('用户点击取消')
        }
      }
    })
  },

  /**
   * 添加用户的和url
   */
  addPlayer: function (uid, url, me) {
    console.log("----- add players");
    var index = -1;
    for (var i = 0; i < 6; i++) {
      if (this.data.players[i]["uid"] == uid) {
        index = i;
      }
    }
    if (index == -1) {
      for (var i = 0; i < 6; i++) {
        if (this.data.players[i].state == 0) {
          index = i;
          break;
        }
      }
    }

    if (index == -1) {
      //TODO. 
    } else {
      let players = this.data.players;
      players[index]["state"] = 1;
      players[index]["videourl"] = url;
      players[index]["uid"] = uid;
      players[index]["me"] = me;
      this.setData({ players: players });
      console.log(players[index]["state"] + players[index]["me"] + "--------");
    }
  },

  updatePlayer: function (uid, options) {
    var index = -1;
    for (var i = 0; i < 6; i++) {
      if (this.data.players[i]["uid"] == uid) {
        index = i;
      }
    }
    if (index != -1) {
      players = this.data.players
      player[i] = Object.assign(player[i], options)
    }
  },

  /**
   * 移除用户
   */
  removePlayer: function (uid) {
    let index = -1;
    for (var i = 0; i < 6; i++) {
      if (this.data.players[i]["uid"] == uid) {
        index = i;
        break;
      }
    }

    if (index == -1) {
      //TODO...
    } else {
      let players = this.data.players;
      players[index] = { "state": 0 };
      this.setData({ players: players });
      console.log("removeplayer" + uid);
    }

  },

  /**
   * 初始化sdk推流
   */
  initAgoraChannel: function (uid, channel) {
    return new Promise((resolve, reject) => {
      let client = new AgoraMiniappSDK.Client();
      //subscribe stream events
      this.subscribeEvents(client);
      AgoraMiniappSDK.LOG.onLog = (text) => {
        Utils.log(text);
      };
      AgoraMiniappSDK.LOG.setLogLevel(-1);
      this.client = client;
      client.init(APPID, () => {
        Utils.log(`client init success`);
        client.join(undefined, channel, uid, () => {
          Utils.log(`client join channel success`);
          //and get my stream publish url
          console.log("------------------++++")
          client.publish(url => {
            Utils.log(`client publish success`);
            console.log("------------------++++")
            resolve(url);
          }, e => {
            console.log("------------------++++")
            Utils.log(`client publish failed: ${e.code} ${e.reason}`);
            reject(e)
          });
        }, e => {
          Utils.log(`client join channel failed: ${e.code} ${e.reason}`);
          console.log("------------------++++")
          reject(e)
        })
      }, e => {
        console.log("------------------++++")
        Utils.log(`client init failed: ${e.code} ${e.reason}`);
        reject(e);
      });
    });
  },
  /**
   * 注册stream事件
   */
  subscribeEvents: function (client) {
    client.on("stream-added", uid => {
      Utils.log(`stream ${uid} added`);
      client.subscribe(uid, url => {
        Utils.log(`stream subscribed successful`);
        this.data.playUrls.push({ key: uid, uid: uid, src: url });
        //important, play/push sequence decide the layout z-index
        //to put pusher bottom, we have to wait until pusher loaded
        //and then play other streams
        if (!this.data.pushing) {
        }
        this.addPlayer(uid, url, 0);

      }, e => {
        Utils.log(`stream subscribed failed ${e.code} ${e.reason}`);
      });
    });

    client.on("stream-removed", uid => {
      Utils.log(`stream ${uid} removed`);
      this.data.playUrls = this.data.playUrls.filter(urlObj => {
        return `${urlObj.uid}` !== `${uid}`;
      });
      //important, play/push sequence decide the layout z-index
      //to put pusher bottom, we have to wait until pusher loaded
      //and then play other streams
      if (!this.data.pushing) {
      }
      this.removePlayer(uid);
    });

    client.on("error", err => {
      let errObj = err || {};
      let code = errObj.code || 0;
      let reason = errObj.reason || "";
      Utils.log(`error: ${code}, reason: ${reason}`);
      if (`${code}` === `${901}`) {
        wx.showToast({
          title: `链接断开`,
          icon: 'none',
          duration: 2000
        });
        this.reconnectTimer = setTimeout(() => {
          this.reconnect();
        }, 5000);
      }
    });
  },

  reconnect: function () {
    Utils.log(`start reconnect`);
    let channel = this.channel;
    let uid = this.uid;

    // this is setData callback
    this.initAgoraChannel(uid, channel).then(url => {
      Utils.log(`re-join channel: ${channel}, uid: ${uid}`);
      Utils.log(`re-pushing ${url}`);
      let size = this.layouter.adaptPusherSize(1);
      addPlayer(uid, url, 1);
    }).catch(e => {
      wx.showToast({
        title: `重连失败: ${e.code} ${e.reason}`,
        icon: 'none',
        duration: 2000
      });
    })
  },

  /*
  *点击排麦按钮后页面出现的效果
  */
  addSongToList: function (option) {
    console.log("------- addSongToList" + JSON.stringify(this.data.order));
    var animation = wx.createAnimation({
      duration: 500,
      timingFunction: 'ease-out'
    })
    let order = this.data.order;
    order["flag"] = false;
    order["waitingList"] = []
    for (var i = 0; i < 10; i++) {
      order["waitingList"].push({
        sid: 204102,
        nickname: "小可爱",
        author: "正易迅",
        name: "再爱一万年",
        status: 1
      })
    }
    order["waitingList"][0]["status"] = 2

    this.setData({
      order: order
    })
    animation.translate(0, 100).step();
    return true;
  },

  /*
  隐藏歌单列表
  */
  hideSongList: function (option) {
    console.log("-------hideSongList");
    let order = this.data.order;
    order["flag"] = true;
    this.setData({ order: order })
  },
  /*
  点击删除按钮触发的事件
  */
  deleteSongFromList: function (e) {
    console.log(e.currentTarget.dataset.id);
    var manager = this;
    wx.showModal({
      title: '确定删除这首歌吗？',
      content: '别害羞，和大家一起唱歌，最重要的就是开心啦~',
      cancelColor: 'red',
      success: function (res) {
        if (res.confirm) {
          let waitingList = manager.data.order.waitingList;
          for (var i = 0; i < waitingList.length; i++) {
            if (e.currentTarget.dataset.id == waitingList[i].id) {
              waitingList.splice(i, 1);
              console.log("+++++ delete")
              break;
            }
          }
          let order = manager.data.order;
          order["waitingList"] = waitingList;
          app.globalData.waitingList = waitingList;
          manager.setData({ order: order });
          console.log("确认")
        }
        else if (res.cancel) {
          console.log('用户点击取消')
        }
      }
    })
  },

  musicController: function () {
    wx.navigateTo({
      url: '../selectsongs/selectsongs',
    })
  },


  stopPlayers: function (users) {
    Utils.log(`stop players: ${JSON.stringify(users)}`);
    let uid = this.uid;
    users.forEach(user => {
      if (`${user.uid}` === `${uid}`) {
        return;
      }
      Utils.log(`stop player ${user.uid}`);
      let context = wx.createLivePlayerContext(`player-${user.uid}`, this);
      context.stop();
    });
  },
  /* 获取文本显示宽度函数 */
  getTextWidth: function (str) {
    const ctx = wx.createCanvasContext('myCanvas');
    // ctx.font = 'italic bold 20px curive'
    ctx.setFontSize(16);
    return ctx.measureText(str).width;
  },
  getFloatWidth: function (sentence) {
    let str = "";

    let slices = sentence["slices"];

    for (var i = 0; i < slices.length; i++) {
      str += slices[i]["word"];
    }
    // 寻找正在播放的那个字的宽度
    let index = -1;
    let playTime = (new Date()).getTime() - this.data.lyric["timestamp"];
    for (var i = 0; i < slices.length; i++) {
      if (slices[i]["timestamp"] <= playTime && playTime <= slices[i]["timestamp"] + slices[i]["duration"]) {
        index = i;
        break;
      }
    }
    //console.log("index:" + index + ", " + playTime);
    if (index == -1) {
      return 0;
    }
    else {
      let prefix = "";
      for (var i = 0; i < index; i++) {
        prefix += slices[i]["word"];
      }
      // 前一部分文字的宽度
      let prefixWidth = this.getTextWidth(prefix);

      // 得到正在播放的那个字的宽度
      let currentWordWidth = this.getTextWidth(slices[index]["word"]);

      // 计算总宽度
      let totalWidth = prefixWidth + (playTime - slices[index]["timestamp"]) * currentWordWidth / slices[index]["duration"];

      //console.log("playTime: " + playTime + ", " + ", "+ (sentence["timestamp"] + sentence["duration"]) + ", prefixwidth: " + totalWidth + ", totalWidth" + this.getTextWidth(str));
      return totalWidth;
    }
  },
  // 倒计时
  playLyric: function () {
    let manager = this;

    if (manager.lrcTimer == null) {
      manager.lrcTimer = setTimeout(function () {
        let lyric = manager.data.lyric;

        if (lyric["index"] == -1 || lyric["index"] > lyric["lrc"]["sentences"].length) {
          manager.lrcTimer = null;
          return 0;
        }
        var index = lyric["index"];
        let sentences = lyric["lrc"]["sentences"];
        var newIndex = -1;
        let currentTime = (new Date()).getTime() - lyric["timestamp"];
        for (var i = index; i < sentences.length; i++) {
          if (sentences[i]["timestamp"] + sentences[i]["duration"] >= currentTime) {
            newIndex = i;
            break;
          }
        }
        lyric["index"] = newIndex;
        manager.setData({ lyric: lyric });
        if (newIndex == -1) {
          manager.lrcTimer = null;
          return 0;
        }



        if (newIndex % 2 == 0) {
          lyric["left_float"] = manager.getFloatWidth(sentences[newIndex]);
          lyric["right_float"] = 0;
          lyric["lyric_left"] = "";
          for (var i = 0; i < sentences[newIndex]["slices"].length; i++) {
            lyric["lyric_left"] += sentences[newIndex]["slices"][i]["word"];
          }
          lyric["lyric_right"] = "";
          if (newIndex < sentences.length) {
            for (var i = 0; i < sentences[newIndex + 1]["slices"].length; i++) {
              lyric["lyric_right"] += sentences[newIndex + 1]["slices"][i]["word"];
            }
          }
        } else {
          lyric["left_float"] = 0;
          lyric["right_float"] = manager.getFloatWidth(sentences[newIndex]);
          lyric["lyric_right"] = "";
          for (var i = 0; i < sentences[newIndex]["slices"].length; i++) {
            lyric["lyric_right"] += sentences[newIndex]["slices"][i]["word"];
          }
          lyric["lyric_left"] = "";
          if (newIndex < sentences.length) {
            for (var i = 0; i < sentences[newIndex + 1]["slices"].length; i++) {
              lyric["lyric_left"] += sentences[newIndex + 1]["slices"][i]["word"];
            }
          }
        }
        manager.setData({ lyric: lyric });

        manager.lrcTimer = null;
        manager.playLyric();
      }, 50);
    }
  },
});




